package com.skilltrackedu.utils;


import cn.hutool.core.exceptions.ValidateException;
import cn.hutool.jwt.JWT;
import cn.hutool.jwt.JWTValidator;
import cn.hutool.jwt.signers.JWTSigner;
import cn.hutool.jwt.signers.JWTSignerUtil;
import com.skilltrackedu.constants.UserConstants;
import com.skilltrackedu.exception.enums.AuthError;
import com.skilltrackedu.exception.exception.AuthException;
import org.springframework.stereotype.Component;

import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.time.Duration;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * JWT工具类，用于生成和验证JWT令牌
 */
@Component
public class JwtTool {
    // ===================== 配置区域 =====================
    private static final Duration DEFAULT_TOKEN_TTL = Duration.ofMinutes(30); // token 过期时间：30分钟

    private static final String SIGN_ALGORITHM = "rs256"; // 签名算法

    private final JWTSigner jwtSigner;

    // 初始化密钥对
    private static KeyPair generateKeyPair() {
        try {
            KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
            generator.initialize(2048); // 密钥长度
            return generator.generateKeyPair();
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("RSA密钥生成失败", e);
        }
    }

    /**
     * 构造方法，初始化签名器
     */
    public JwtTool() {
        KeyPair keyPair = generateKeyPair();
        this.jwtSigner = JWTSignerUtil.createSigner(SIGN_ALGORITHM, keyPair);
    }


    /**
     * 创建 access-token
     *
     * @param userId 用户信息
     * @return access-token
     */
    public String createToken(Long userId, List<String> roles, Duration ttl) {
        // 1.生成jws
        return JWT.create()
                .setPayload(UserConstants.USER_ID_KEY, userId)  // 设置用户id
                .setPayload(UserConstants.ROLES_KEY , roles)  // 设置用户角色(权限)
                .setExpiresAt(new Date(System.currentTimeMillis() + ttl.toMillis()))  //设置token过期时间
                .setSigner(jwtSigner)  // 设置签名算法(已经在上面初始化过了// )
                .sign();
    }

    /**
     * 解析token
     *
     * @param token token
     * @return 解析刷新token得到的用户信息
     */
    public Map parseToken(String token) {
        // 1.校验token是否为空
        if (token == null) {
            AuthException.cast(AuthError.UNAUTHORIZED_NOT_LOGGED_IN);
        }
        // 2.校验并解析jwt
        JWT jwt = null;
        try {
            jwt = JWT.of(token).setSigner(jwtSigner);
        } catch (Exception e) {
            AuthException.cast(AuthError.UNAUTHORIZED_TOKEN_INVALID.getErrMessage());
        }
        // 2.校验jwt是否有效
        if (!jwt.verify()) {
            // 验证失败
            AuthException.cast(AuthError.UNAUTHORIZED_TOKEN_INVALID.getErrMessage());
        }
        // 3.校验是否过期
        try {
            JWTValidator.of(jwt).validateDate();
        } catch (ValidateException e) {
            AuthException.cast(AuthError.UNAUTHORIZED_TOKEN_EXPIRED.getErrMessage());
        }
        // 4.数据格式校验
        Object userPayload = jwt.getPayload(UserConstants.USER_ID_KEY); // 获取用户id
        Object rolesPaylod = jwt.getPayload(UserConstants.ROLES_KEY);  // 获取用户角色(权限)
        if (userPayload == null || rolesPaylod == null) {
            // 数据为空
            AuthException.cast(AuthError.UNAUTHORIZED_TOKEN_INVALID.getErrMessage());
        }

        // 5.数据解析
        try {
            Long userId = Long.valueOf(userPayload.toString());
            List<String> roles = (List<String>) rolesPaylod;

            //map封装结果
            Map<String, Object> result = new HashMap<>();
            result.put(UserConstants.USER_ID_KEY, userId);
            result.put(UserConstants.ROLES_KEY, roles);

            return result;
        } catch (RuntimeException e) {
            // 数据格式有误
            AuthException.cast(AuthError.UNAUTHORIZED_TOKEN_INVALID.getErrMessage());
        }
        // 防止编译器警告，理论上不会到达此处
        return null;
    }
}